define(['config', 'promise', 'fastclick'], function (Config, _Promise, FastClick) {
  if (!window.Promise) { // Promise 兼容
    _Promise.polyfill()
  }
  window.apiready = function () {
    var evt = document.createEvent('HTMLEvents')
    evt.initEvent('apiready', false, false)
    window.dispatchEvent(evt)
  }
  function _apiready (fn) {
    if (typeof (api) === 'object') {
      fn()
      return
    }
    window.addEventListener('apiready', function () {
      fn()
    })
  }

  let u = {}
  u.apiready = _apiready
  u.addCls = function (el, cls) {
    if ('classList' in el) {
      el.classList.add(cls)
    } else {
      var preCls = el.className
      var newCls = preCls + ' ' + cls
      el.className = newCls
    }
    return el
  }
  u.removeCls = function (el, cls) {
    if ('classList' in el) {
      el.classList.remove(cls)
    } else {
      var preCls = el.className
      var newCls = preCls.replace(cls, '')
      el.className = newCls
    }
    return el
  }
  u.formatTime = function (ms, fmt) {
    var date = new Date(ms)
    var o = {
      'M+': date.getMonth() + 1, // 月份
      'd+': date.getDate(), // 日
      'h+': date.getHours(), // 小时
      'm+': date.getMinutes(), // 分
      's+': date.getSeconds(), // 秒
      'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
      'S': date.getMilliseconds(), // 毫秒
      'A': (function () {
        if (date.getHours() <= 12) {
          return '上午' + date.getHours()
        } else {
          return '下午' + (date.getHours() - 12)
        }
      })()
    }
    if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) }
    for (var k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
    }
    return fmt
  }
  // 判断是否为false，空数组，空对象
  u.isEmpty = function (value) {
    if (!value) {
      return true
    }
    if (Array.isArray(value) && value.length === 0) {
      return true
    }
    if (typeof value === 'object' && JSON.stringify(value) === '{}') {
      return true
    }
    return false
  }
  u.loadCss = function (url) {
    var link = document.createElement('link')
    link.type = 'text/css'
    link.rel = 'stylesheet'
    link.href = url
    document.getElementsByTagName('head')[0].appendChild(link)
  }

  FastClick.attach(document.body)

  u.toast = function ({msg, duration = 3000, location = 'bottom'} = {}) {
    _apiready(function () {
      api.toast({
        msg: msg,
        duration: duration,
        location: location
      })
    })
  }

  u.showProgress = function ({
    title = '努力加载中',
    text = '请稍候',
    modal = true} = {}) {
    _apiready(() => {
      api.showProgress({
        title: title,
        text: text,
        modal: modal
      })
    })
  }

  u.ajax = _ajax
  function _ajax ({url, type = 'get', data, cache = true, loading = false}) {
    // Host 切换
    let Host = ''
    switch (Config.env) {
      case 'dev':
        Host = Config.devHost
        break
      case 'prod':
        Host = Config.prodHost
        break
      default:
        Host = Config.prodHost
    }
    // get 参数整合
    if (type.match(/get/i) && typeof (data) === 'object') {
      let wrap = ''
      for (var j in param) {
        wrap += '&' + j + '=' + param[j]
      }
      if (url.indexOf('?') !== -1) {
        url += wrap
      } else {
        url += '?' + wrap.replace('&', '')
      }
    }

    return new Promise((resolve, reject) => {
      _apiready(() => {
        if (loading) {
          u.showProgress()
        }

        api.ajax({
          url: Host + url,
          merhod: type,
          cache: cache,
          timeout: Config.ajaxTimeout,
          dataType: 'json',
          headers: {
            'Content-Type': 'application/json'
          },
          returnAll: true,
          data: {
            body: data
          }
        }, (ret, err) => {
          api.hideProgress()
          if (ret) {
            resolve(ret.body)
            if (Config.ajaxLog) {
              console.log(ret)
            }
          } else {
            reject(err)
            if (Config.ajaxLog) {
              console.log(err)
            }
          }
        })
      })
    })
  }

  u.openWin = function ({
    name, url, data, pageParam, delay = 50, reload = false}) {
    _apiready(function () {
      api.openWin({
        name: name,
        url: url,
        pageParam: pageParam,
        delay: delay,
        reload: reload
      })
    })
  }
  u.openFrame = function ({
    name, url, rect, pageParam, bounces = true, bgColor} = {}) {
    _apiready(function () {
      let arg = {
        name: name,
        url: url,
        rect: rect,
        pageParam: pageParam || api.pageParam, // 默认传入win的pageParam
        bounces: bounces
      }
      if (bgColor) {
        arg.bgColor = bgColor
      }
      api.openFrame(arg)
    })
  }

  u.pageLoading = {
    show () {
      let loadingDom = document.createElement('div')
      loadingDom.id = 'app-loading'
      loadingDom.innerHTML = `
      <div class="app-loading__mask">
        <div class="app-loading__contain"></div>
      </div>`
      document.body.appendChild(loadingDom)
    },
    hide () {
      let loadingDom = document.querySelector('#app-loading')
      loadingDom.addEventListener('webkitTransitionEnd', function () {
        document.body.removeChild(loadingDom)
      })
      u.addCls(loadingDom, 'hide')
    }
  }

  u.forbidBack = _forbidBack
  function _forbidBack () {
    _apiready(function () {
      api.addEventListener({
        name: 'keyback'
      }, function (ret, err) {

      })
      api.setWinAttr({
        slidBackEnabled: false
      })
    })
  }

  u.refreshHeader = function (callback) {
    _apiready(function () {
      api.setRefreshHeaderInfo({
        visible: true,
        loadingImg: 'widget://image/refreshHeader.png',
        bgColor: '#fff',
        textColor: '#1d1d26',
        textDown: '下拉刷新...',
        textUp: '松开刷新...',
        showTime: false
      }, function (ret, err) {
      // 在这里从服务器加载数据，加载完成后调用api.refreshHeaderLoadDone()方法恢复组件到默认状态
        callback()
      })
    })
  }

  u.call = function (num) {
    _apiready(function () {
      api.call({
        type: 'tel_prompt',
        number: num + ''
      })
    })
  }

  u.verify = function (type, value) {
    switch (type) {
      case 'phone':
        return /1\d{10}/.test(value)
      case 'code':
        return /\d{4}/.test(value)
      case 'password':
        return /^[a-zA-Z0-9]{6,21}$/.test(value)
    }
  }
  u.dom = _dom
  function _dom (el, selector) {
    if (arguments.length === 1 && typeof arguments[0] === 'string') {
      if (document.querySelector) {
        return document.querySelector(arguments[0])
      }
    } else if (arguments.length === 2) {
      if (el.querySelector) {
        return el.querySelector(selector)
      }
    }
  }
  u.domAll = _domAll
  function _domAll (el, selector) {
    if (arguments.length === 1 && typeof arguments[0] === 'string') {
      if (document.querySelectorAll) {
        return document.querySelectorAll(arguments[0])
      }
    } else if (arguments.length === 2) {
      if (el.querySelectorAll) {
        return el.querySelectorAll(selector)
      }
    }
  }
  u.trim = _trim
  // 去除两端空格
  function _trim (str) {
    if (String.prototype.trim) {
      return str == null ? '' : String.prototype.trim.call(str)
    } else {
      return str.replace(/(^\s*)|(\s*$)/g, '')
    }
  };
  u.offset = _offset
  // 获取元素在页面(不是窗口)中的位置与宽高
  function _offset (selector) {
    var el = document.querySelector(selector)
    var sl = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft)
    var st = Math.max(document.documentElement.scrollTop, document.body.scrollTop)

    var rect = el.getBoundingClientRect()
    return {
      l: rect.left + sl,
      t: rect.top + st,
      w: el.offsetWidth,
      h: el.offsetHeight
    }
  }

  // LocalStorage
  function uzStorage () {
    var ls = window.localStorage
    // if(isAndroid){
    //    ls = os.localStorage();
    // }
    return ls
  };
  u.setStorage = _setStorage
  u.getStorage = _getStorage
  u.rmStorage = _rmStorage
  u.clearStorage = _clearStorage
  function _setStorage (key, value) {
    if (arguments.length === 2) {
      var v = value
      if (typeof v === 'object') {
        v = JSON.stringify(v)
        v = 'obj-' + v
      } else {
        v = 'str-' + v
      }
      var ls = uzStorage()
      if (ls) {
        ls.setItem(key, v)
      }
    }
  }
  function _getStorage (key) {
    var ls = uzStorage()
    if (ls) {
      var v = ls.getItem(key)
      if (!v) { return }
      if (v.indexOf('obj-') === 0) {
        v = v.slice(4)
        return JSON.parse(v)
      } else if (v.indexOf('str-') === 0) {
        return v.slice(4)
      }
    }
  }
  function _rmStorage (key) {
    var ls = uzStorage()
    if (ls && key) {
      ls.removeItem(key)
    }
  }
  function _clearStorage () {
    var ls = uzStorage()
    if (ls) {
      ls.clear()
    }
  }

  // 屏幕上下Padding
  u.fixStatusBar = function (selector) {
    _dom(selector).style.paddingTop = _getStorage('statusBarPadding') + 'px'
  }
  u.fixTabBar = function (selector) {
    _dom(selector).style.paddingBottom = _getStorage('tabBarPadding') + 'px'
  }

  // 事件相关
  u.on = function (event, cb) {
    api.addEventListener({
      name: event
    }, function (ret, err) {
      cb(ret.value)
    })
  }
  u.off = function (event) {
    api.removeEventListener({
      name: event
    })
  }
  u.emit = function (event, data) {
    api.sendEvent({
      name: event,
      extra: data // 字符串或对象
    })
  }

  window.app = u
  return u
})
